/*
 * Project it.battlehorse.rcp.tools.log
 * Created on Nov 19, 2005
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * A copy of the LGPL is available also at
 * http://www.gnu.org/copyleft/lesser.html
 * 
 */
package it.battlehorse.rcp.tools.log.views;

import it.battlehorse.rcp.sl.annot.Injected;
import it.battlehorse.rcp.sl.annot.Serviceable;
import it.battlehorse.rcp.tools.log.LogCollector;
import it.battlehorse.rcp.tools.log.actions.DeleteAllLogAction;
import it.battlehorse.rcp.tools.log.actions.DeleteCurrentLogAction;
import it.battlehorse.rcp.tools.log.actions.ShowLogDetailAction;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;

/**
 * Defines the view which collects log events for the Actor perspective
 * 
 * @author battlehorse
 * @since Nov 19, 2005
 */
@Serviceable
public class ActorLogView extends ViewPart {
	
	/**
	 * The view id, whose value is {@value }.
	 */
	public static final String ID_VIEW = "it.battlehorse.rcp.tools.log.views.ActorLogView";
	
	/* The content provider */
	private ActorLogContentProvider contentProvider;
	
	/* The label provider */
	private ITableLabelProvider labelProvider;
	
	/**
	 * The position of the column which shows the severity of the log item
	 */
	public final static int COLUMN_SEVERITY = 0;
	
	/**
	 * The position of the column which shows the time of the log item
	 */
	public final static int COLUMN_TIME = 2;
	
	/**
	 * The position of the column which shows the source of the log item
	 */
	public final static int COLUMN_SOURCE = 3;
	
	/**
	 * The position of the column which shows the type of the log item
	 */
	public final static int COLUMN_TYPE = 4;
	
	/**
	 * The position of the column which shows the message contained in the log item
	 */
	public final static int COLUMN_MESSAGE = 1;
	
	/* The Action which deletes all the log items */
	private Action deleteAllItem;
	
	/* The Action which deletes the current log item */
	private DeleteCurrentLogAction deleteCurItem;
	
	/* The Action which shows the details of the current log item */
	private ShowLogDetailAction showDetail;
			
	private TableViewer viewer;
	
	private LogCollector collector;
	
	/**
	 * Injects the log collector into this object
	 * 
	 * @param collector the log collector
	 */
	@Injected
	public void setLogCollector(LogCollector collector) {
		this.collector = collector;
	}
	
	@Override public void init(IViewSite site, IMemento memento) throws PartInitException {
		super.init(site,memento);
		
		
		contentProvider = new ActorLogContentProvider(this);
		labelProvider = new ActorLogLabelProvider();
		
		collector.addLogListener(contentProvider);
	}
	

	@Override public void createPartControl(Composite parent) {
		
		 viewer = new TableViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL);
		 
		 Table t = viewer.getTable();
		 
		 new TableColumn(t, SWT.LEFT).setText("Severity");
		 new TableColumn(t, SWT.LEFT).setText("Message");		 
		 new TableColumn(t, SWT.LEFT).setText("Time");
		 new TableColumn(t, SWT.LEFT).setText("Source");		 
		 new TableColumn(t, SWT.LEFT).setText("Type");
		 
		 for (TableColumn col : t.getColumns()) 
			 col.pack();
		 
		 t.setLinesVisible(true);
		 t.setHeaderVisible(true);
		 
		 viewer.setContentProvider(contentProvider);		 		 
		 viewer.setLabelProvider(labelProvider);
		 viewer.setInput("root");
		 
		 createActions(viewer);
		 createContextMenu(viewer);
		 createToolbar();
		 attachEvents(viewer);
		 
	}

	@Override public void setFocus() {
		viewer.getControl().setFocus();

	}
	
	@Override public void dispose() {
		collector.removeLogListener(contentProvider);		
		
		super.dispose();
	}
	
	/**
	 * Refreshes the table viewer and ensures that the last inserted element
	 * is visible (if not null)
	 * 
	 * @param lastInsertedElement the last inserted element, or {@code null} if
	 * 	the last operation was not an insert.
	 */
	void refresh(final Object lastInsertedElement) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (viewer != null && !viewer.getControl().isDisposed()) {
					viewer.refresh(true);
					Table t = viewer.getTable();
				
					for (TableColumn col : t.getColumns()) 
						col.pack();
				 
					if (lastInsertedElement != null)
						viewer.reveal(lastInsertedElement);
				}
			}
		});
	}
	
	/**
	 * Creates the actions
	 * 
	 * @param viewer
	 */
	private void createActions(TableViewer viewer) {
		deleteCurItem = new DeleteCurrentLogAction(contentProvider, viewer);
		deleteAllItem = new DeleteAllLogAction(contentProvider);
		showDetail = new ShowLogDetailAction(viewer);
	}
	
    /**
     * Create toolbar.
     */
    private void createToolbar() {    		    	
        IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
        mgr.add(showDetail);
        mgr.add(deleteCurItem);
        mgr.add(deleteAllItem);
    }
    
    /**
     * Creates the context menu associated with log items
     * 
     * @param viewer
     */
    private void createContextMenu(TableViewer viewer) {
        // Create menu manager.
    	MenuManager menuMgr = new MenuManager();
    	menuMgr.setRemoveAllWhenShown(true);
    	menuMgr.addMenuListener(new IMenuListener() {
    		public void menuAboutToShow(IMenuManager mgr) {
    			fillContextMenu(mgr);
    		}
    	});
        
        // Create menu.
    	Menu menu = menuMgr.createContextMenu(viewer.getControl());
        viewer.getControl().setMenu(menu);
        
        // Register menu for extension.
        getSite().registerContextMenu(menuMgr, viewer);
    }
    
    /**
     * Populates the context menu associated with log items
     * 
     * @param mgr
     */
    private void fillContextMenu(IMenuManager mgr) {
    	
    	mgr.add(showDetail);
    	mgr.add(new Separator());
    	
    	mgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
    	mgr.add(deleteCurItem);        
        mgr.add(deleteAllItem);
    }
    
    /**
     * Attachs click events and key events to the log viewer
     * 
     * @param viewer
     */
    private void attachEvents(TableViewer viewer) {
    	viewer.addDoubleClickListener(showDetail); 
    	viewer.getControl().addKeyListener(deleteCurItem);
    }

}
